import { isString, isArray, saveFile } from '.';
export type SelectFileAccept = 'docx' | 'ppt' | 'xls' | 'jpg' | 'jpeg' | 'png' | 'pdf' | 'mp4' | 'mp3';

interface SelectFileOption {
	accept?: SelectFileAccept[];
	multiple?: boolean;
}

const acceptToAttribute = (accept: SelectFileAccept[]) => {
	let types: string[] = [];
	if (accept.includes('docx')) {
		types.push('.docx,.doc');
	}
	if (accept.includes('ppt')) {
		types.push('.ppt,.pptx');
	}
	if (accept.includes('xls')) {
		types.push('.xls,.xlsx');
	}
	if (accept.includes('png')) {
		types.push('.png');
	}
	if (accept.includes('jpg')) {
		types.push('.jpg');
	}
	if (accept.includes('jpeg')) {
		types.push('.jpeg');
	}
	if (accept.includes('pdf')) {
		types.push('.pdf');
	}
	if (accept.includes('mp3')) {
		types.push('.mp3');
	}
	if (accept.includes('mp4')) {
		types.push('.mp4');
	}
	return types.join(',');
};

export const selectFile = ({ accept, multiple }: SelectFileOption = {}) =>
	new Promise<{
		tempFilePaths: string[];
		tempFiles: UniApp.ChooseFileSuccessCallbackResultFile[];
	}>((resolve, reject) => {
		uni.chooseFile({
			count: multiple ? undefined : 1,
			extension: accept,
			success(res) {
				resolve({
					tempFilePaths: isArray(res.tempFilePaths) ? res.tempFilePaths : [res.tempFilePaths],
					tempFiles: isArray(res.tempFiles)
						? (res.tempFiles as UniApp.ChooseFileSuccessCallbackResultFile[])
						: [res.tempFiles as UniApp.ChooseFileSuccessCallbackResultFile]
				});
			},
			fail(err) {
				reject(err);
			}
		});
	});

/**
 * 通过读取文件流前几个字节来判断文件格式 源码来自file-type 详见：https://www.npmjs.com/package/file-type
 */
const checkFile = (headers: number[]) => {
	return (fileView: Uint8Array, offset?: number) => {
		return headers.every((header, index) => header === fileView[index + (offset || 0)]);
	};
};
const isJpeg = checkFile([0xff, 0xd8, 0xff]);
const isPng = checkFile([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
const isPdf = checkFile([0x25, 0x50, 0x44, 0x46]);
const isMp3 = checkFile([0x02, 0x06]);
// const isMp4 = checkFile([0x25, 0x50, 0x44, 0x46])

const isZip = checkFile([0x50, 0x4b, 0x3, 0x4]);

const getFileView = (file: UniApp.ChooseFileSuccessCallbackResultFile) => {
	return new Promise<Uint8Array>((resolve, reject) => {
		const fileReader = new FileReader();
		fileReader.onload = () => {
			const fileView = new Uint8Array(fileReader.result as ArrayBuffer);
			resolve(fileView);
		};
		fileReader.onerror = reject;
		fileReader.readAsArrayBuffer(file);
	});
};

export const getFileType = async (file: UniApp.ChooseFileSuccessCallbackResultFile): Promise<SelectFileAccept | undefined> => {
	const fileView = await getFileView(file);
	// docx、xls都是zip
	if (isZip(fileView)) {
		// 简单判断下类型，此类文件严格类型判断需读取文件流，可参考npm上的file-type
		// docx
		if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
			return 'docx';
		}
		// pptx
		if (file.type === 'application/vnd.openxmlformats-officedocument.presentationml.presentation') {
			return 'ppt';
		}
		// xlsx
		if (file.type === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') {
			return 'xls';
		}
	}
	// 简单判断下类型，此类文件严格类型判断需读取文件流，可参考npm上的file-type
	// doc
	if (file.type === 'application/msword') {
		return 'docx';
	}
	// ppt
	if (file.type === 'application/vnd.ms-powerpoint') {
		return 'ppt';
	}
	// xls
	if (file.type === 'application/vnd.ms-excel') {
		return 'xls';
	}
	// mp4
	if (file.type === 'video/mp4') {
		return 'mp4';
	}
	// mp3
	if (file.type === 'video/mp3') {
		return 'mp3';
	}

	if (isPng(fileView)) {
		return 'png';
	}
	if (isJpeg(fileView)) {
		return 'jpg';
	}
	if (isJpeg(fileView)) {
		return 'jpeg';
	}
	if (isPdf(fileView)) {
		return 'pdf';
	}
	return undefined;
};

// 文件类型检测
export const checkFileType = async (files: UniApp.ChooseFileSuccessCallbackResultFile[], accept: SelectFileAccept | SelectFileAccept[]) => {
	let types = isString(accept) ? [accept] : accept;

	const arr: Array<{
		type: SelectFileAccept | undefined;
		file: UniApp.ChooseFileSuccessCallbackResultFile;
	}> = [];
	for (let item of files) {
		const type = await getFileType(item);
		arr.push({
			file: item,
			type: type
		});
	}
	return arr.find((item) => {
		if (!item.type || !types.includes(item.type)) {
			return true;
		}
	});
};

const MB = 1024 * 1024;
// 文件大小检测
export const checkFileSize = (size: number, num = 0) => {
	if (!num) {
		return true;
	}
	return size > num * MB;
};

// 文件大小带上单位
export const fileSizeToUnit = (size: number, toMB = true) => {
	if (toMB) {
		size = size * MB;
	}
	if (size < 1024) {
		return size + 'B';
	} else if (size < 1048576) {
		return (size / 1024).toFixed(2) + 'KB';
	} else if (size < 1073741824) {
		return (size / 1048576).toFixed(2) + 'MB';
	} else {
		return (size / 1073741824).toFixed(2) + 'GB';
	}
};
// 文件下载
export const downLoadFile = async (url: string, name: string) => {
	
	// #ifndef H5
	const res = await uni.downloadFile({
		url
	});
	saveFile({tempFilePath:res.tempFilePath});
	// #endif
	// #ifdef H5
	let aLink = document.createElement('a');
	aLink.style.display = 'none';
	aLink.href = url;
	aLink.target = '_blank';
	aLink.setAttribute('download',name);

	// 触发点击-然后移除
	document.body.appendChild(aLink);
	if (document.all) {
		aLink.click();
	} else {
		// 兼容 Firfox
		const evt = document.createEvent('MouseEvents');
		evt.initEvent('click', true, true);
		aLink.dispatchEvent(evt);
	}
	document.body.removeChild(aLink);
	// #endif
};
